package com.dyp.myapp.web.rest;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@RestController
@RequestMapping("/api")
public class AsyncResource {

    private ExecutorService executor = Executors.newCachedThreadPool();


    @GetMapping(value = "/manue/sse", produces = "text/event-stream;charset=UTF-8")
    public String manueSse(){
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        return "ABC:" + new Date() + "\n\n";
    }

    private ExecutorService nonBlockingService = Executors
        .newCachedThreadPool();
    @GetMapping("/rbe")
    public ResponseEntity<ResponseBodyEmitter> handleRbe() {
        ResponseBodyEmitter emitter = new ResponseBodyEmitter();
        executor.submit(() -> {
            try {
                for(int i = 0; i < 3; i++)
                {
                    Thread.sleep(1000);
                    emitter.send(
                            "/rbe" + " @ " + new Date(), MediaType.TEXT_PLAIN);
                }

                emitter.complete();
            } catch (Exception ex) {
                emitter.completeWithError(ex);
            }
        });
        return new ResponseEntity(emitter, HttpStatus.OK);
    }

    @GetMapping("/sse")
    public SseEmitter handleSse() {
        SseEmitter emitter = new SseEmitter();
        nonBlockingService.execute(() -> {
            try {
                for(int i = 0; i < 3; i++) {
                    Thread.sleep(1000);
                    emitter.send("/sse" + " @ " + new Date());
                }
                // we could send more events
                emitter.complete();
            } catch (Exception ex) {
                emitter.completeWithError(ex);
            }
        });
        return emitter;
    }


    @GetMapping("/srb")
    public ResponseEntity<StreamingResponseBody> handleSrb() {
        StreamingResponseBody stream = out -> {
            for(int i = 0; i < 3; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                String msg = "/srb" + " @ " + new Date();
                out.write(msg.getBytes());
            }
        };
        return new ResponseEntity(stream, HttpStatus.OK);
    }

}
